package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.UacGroupRoleMenuMapper;
import com.csun.cmny.provider.model.constant.RoleConstant;
import com.csun.cmny.provider.model.domain.*;
import com.csun.cmny.provider.model.dto.group.GroupMenuQueryDto;
import com.csun.cmny.provider.model.dto.group.GroupRoleAssignMenuDto;
import com.csun.cmny.provider.model.dto.group.GroupRoleDto;
import com.csun.cmny.provider.model.dto.group.GroupRoleMenuListDto;
import com.csun.cmny.provider.model.dto.menu.MenuQueryDto;
import com.csun.cmny.provider.model.dto.role.AssignMenuDto;
import com.csun.cmny.provider.model.dto.role.RoleAssignMenuDto;
import com.csun.cmny.provider.model.exceptions.UacBizException;
import com.csun.cmny.provider.model.vo.BindAuthVo;
import com.csun.cmny.provider.model.vo.MenuVo;
import com.csun.cmny.provider.resolver.CmnyMessageSource;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.provider.utils.TreeUtil;
import com.csun.cmny.util.PublicUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import java.util.List;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2019-07-21 13:10
 * @Description: the class uac group role menu service impl
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UacGroupRoleMenuServiceImpl extends BaseService<UacGroupRoleMenu>
        implements UacGroupRoleMenuService {

    @Resource
    private CmnyMessageSource cmnyMessageSource;
    @Resource
    private UacGroupRoleMenuMapper uacGroupRoleMenuMapper;
    @Resource
    private UacGroupService uacGroupService;
    @Resource
    private UacRoleService uacRoleService;
    @Resource
    private UacMenuService uacMenuService;
    @Resource
    private UacActionService uacActionService;
    @Resource
    private UacRoleMenuService uacRoleMenuService;

    /**
     * 批量移除机构角色菜单
     *
     * @param groupRoleMenuListDto the group role menu list dto
     * @return the int.
     */
    @Override
    public Integer batchDeleteRoleMenu(GroupRoleMenuListDto groupRoleMenuListDto) {

        Long groupId = groupRoleMenuListDto.getGroupId();
        Long roleId = groupRoleMenuListDto.getRoleId();
        List<Long> menuIdList = groupRoleMenuListDto.getMenuIdList();

        Preconditions.checkArgument(groupId != null,
                cmnyMessageSource.getMessage("group.id.null", null));

        Preconditions.checkArgument(roleId != null,
                cmnyMessageSource.getMessage("role.id.null", null));

//        Preconditions.checkArgument(PublicUtil.isNotEmpty(menuIdList),
//                cmnyMessageSource.getMessage("menu.id.list.null", null));

        return uacGroupRoleMenuMapper.batchDeleteRoleMenu(groupId, roleId, menuIdList);
    }

    /**
     * 分配机构角色菜单
     *
     * @param groupRoleAssignMenuDto the group role assign menu dto
     *
     * @return the int.
     */
    @Override
    public Integer assignRoleMenu(GroupRoleAssignMenuDto groupRoleAssignMenuDto) {

        Long groupId = groupRoleAssignMenuDto.getGroupId();
        Long roleId = groupRoleAssignMenuDto.getRoleId();
        List<AssignMenuDto> assignMenuDtoList = groupRoleAssignMenuDto.getAssignMenuDtoList();

        Preconditions.checkArgument(groupId != null,
                cmnyMessageSource.getMessage("group.id.null", null));

        Preconditions.checkArgument(roleId != null,
                cmnyMessageSource.getMessage("role.id.null", null));

        Preconditions.checkArgument(PublicUtil.isNotEmpty(assignMenuDtoList),
                cmnyMessageSource.getMessage("menu.list.null", null));

        // TODO 校验角色Id是否存在

        // TODO 校验菜单Id是否存在

        List<Long> checkMenuList = Lists.newArrayList();
        List<Long> deleteMenuList = Lists.newArrayList();
        // 将分配的菜单按照'选中','移除'分为两组
        for (AssignMenuDto amd : assignMenuDtoList) {
            switch (amd.getCheck()) {
                case RoleConstant.CHECK_STATUS_SLT :
                    checkMenuList.add(amd.getMenuId());
                    break;
                case RoleConstant.CHECK_STATUS_RID :
                    deleteMenuList.add(amd.getMenuId());
                    break;
            }
        }

        int result = 0;
        // 批量添加角色菜单
        if (PublicUtil.isNotEmpty(checkMenuList)) {
            result += uacGroupRoleMenuMapper.batchSaveRoleMenu(groupId, roleId, checkMenuList);
        }

        // 批量删除角色菜单
        if (PublicUtil.isNotEmpty(deleteMenuList)) {
            result += uacGroupRoleMenuMapper.batchDeleteRoleMenu(groupId, roleId, deleteMenuList);
        }

        return result;
    }

    /**
     * 查询角色菜单列表-分页查询
     *
     * @param groupMenuQueryDto the group menu query dto
     * @return the page info.
     */
    @Override
    public PageInfo queryRoleMenuListWithPage(GroupMenuQueryDto groupMenuQueryDto) {

        Long groupId = groupMenuQueryDto.getGroupId();
        Long roleId = groupMenuQueryDto.getRoleId();

        // 校验角色Id是否为空
        Preconditions.checkArgument(roleId != null,
                cmnyMessageSource.getMessage("role.id.null", null));

        // 校验机构Id是否为空
        Preconditions.checkArgument(groupId != null,
                cmnyMessageSource.getMessage("group.id.null", null));

        List<UacMenu> uacMenuList = Lists.newArrayList();
        // 获取所有绑定的菜单和按钮权限Id集合
        GroupRoleDto groupRoleDto = new GroupRoleDto();
        groupRoleDto.setGroupId(groupId);
        groupRoleDto.setRoleId(roleId);
        List<Long> checkedAuthList = getCheckedMenuList(groupRoleDto);

        // 分页
        PageHelper.startPage(groupMenuQueryDto.getPageNum(), groupMenuQueryDto.getPageSize());
        if (PublicUtil.isEmpty(checkedAuthList)) {
            uacMenuList = uacGroupRoleMenuMapper.queryMenuAndSubMenuListWithPage(groupMenuQueryDto);
        } else {
            groupMenuQueryDto.setMenuIds(StringUtils.join(checkedAuthList, ","));
            // 查询
            uacMenuList= uacGroupRoleMenuMapper.queryRoleMenuListWithPage(groupMenuQueryDto);
        }

        return new PageInfo<>(uacMenuList);
    }

    /**
     * 批量添加机构角色菜单
     *
     * @param groupId         the group id
     * @param uacRoleMenuList the role menu list
     *
     * @return the int.
     */
    @Override
    public Integer batchSaveGroupRoleMenu(Long groupId, List<UacRoleMenu> uacRoleMenuList) {

        return uacGroupRoleMenuMapper.batchSaveGroupRoleMenu(groupId, uacRoleMenuList);
    }

    /**
     * get group role menu tree
     *
     * @param groupRoleDto the group role dto
     *
     * @return the bind auth vo
     */
    @Override
    public BindAuthVo getGroupRoleMenuTree(GroupRoleDto groupRoleDto) {

        BindAuthVo bindAuthVo = new BindAuthVo();

        Long groupId = groupRoleDto.getGroupId();
        Long roleId = groupRoleDto.getRoleId();

        // 校验角色Id是否为空
        Preconditions.checkArgument(roleId != null,
                cmnyMessageSource.getMessage("role.id.null", null));

        // 校验机构Id是否为空
        Preconditions.checkArgument(groupId != null,
                cmnyMessageSource.getMessage("group.id.null", null));

        // 校验机构是否存在
        UacGroup uacGroup = uacGroupService.selectByKey(groupId);
        if (PublicUtil.isEmpty(uacGroup)) {
            throw new UacBizException(ErrorCodeEnum.UAC10015016);
        }

        // 校验角色是否存在
        UacRole uacRole = uacRoleService.selectByKey(roleId);
        if (PublicUtil.isEmpty(uacRole)) {
            throw new UacBizException(ErrorCodeEnum.UAC10012009);
        }

        // 获取所有绑定的菜单和按钮权限Id集合
        List<Long> checkedMenuList = getCheckedMenuList(groupRoleDto);

        boolean check = true;
        // 如果没有选中任何菜单, 为角色全部的菜单
        if (PublicUtil.isEmpty(checkedMenuList)) {  //
            checkedMenuList = uacActionService.getCheckedMenuList(roleId);
            check = false;
        }

        List<UacMenu> uacMenus;

        // 如果该角色没有菜单
        if (PublicUtil.isEmpty(checkedMenuList)) {
            return bindAuthVo;
        } else {
            // 查询角色菜单列表集合
            groupRoleDto.setMenuIds(StringUtils.join(checkedMenuList, ","));
            uacMenus = uacRoleMenuService.queryRoleMenuListWithCheck(groupRoleDto);
        }

        if (!check) {
            for (UacMenu menu : uacMenus) {
                menu.setCheck(0);
            }
        }

        // 合并菜单和按钮权限 递归生成树结构
        List<MenuVo> menuVoList = uacMenuService.getAuthList(uacMenus, null);

        List<MenuVo> tree = TreeUtil.getChildMenuVos(menuVoList, 0L);

        bindAuthVo.setAuthTree(tree);

        bindAuthVo.setCheckedAuthList(checkedMenuList);

        return bindAuthVo;
    }

    /**
     * 查询机构角色选中的菜单Id列表
     *
     * @param groupRoleDto the group role dto
     *
     * @return the list.
     */
    @Override
    public List<Long> getCheckedMenuList(GroupRoleDto groupRoleDto) {

        Long groupId = groupRoleDto.getGroupId();
        Long roleId = groupRoleDto.getRoleId();

        // 校验角色Id是否为空
        Preconditions.checkArgument(roleId != null,
                cmnyMessageSource.getMessage("role.id.null", null));

        // 校验机构Id是否为空
        Preconditions.checkArgument(groupId != null,
                cmnyMessageSource.getMessage("group.id.null", null));

        return uacGroupRoleMenuMapper.getCheckedMenuList(groupRoleDto);
    }

    /**
     * 查询角色-菜单数量
     *
     * @param roleId     the role id
     * @param menuIdList the menu id list
     *
     * @return the int.
     */
    @Override
    public int selectCountRoleIdAndMenuIdList(Long roleId, List<Long> menuIdList) {

        return uacGroupRoleMenuMapper.selectCountRoleIdAndMenuIdList(roleId, menuIdList);
    }

    /**
     * query menu list by group id and user id
     *
     * @param groupId   the group id
     * @param userId    the user id
     *
     * @return the list.
     */
    @Override
    public List<MenuVo> queryMenuListByGroupIdAndUserId(Long groupId, Long userId) {

        return uacGroupRoleMenuMapper.queryMenuListByGroupIdAndUserId(groupId, userId);
    }
}